package com.example.eeuse.server.impl;

import com.example.eeuse.mapper.ee.TaskMonitorMapper;
import com.example.eeuse.model.dto.ChannelStatisticDto;
import com.example.eeuse.model.ee.TaskMonitor;
import com.example.eeuse.model.vo.ChannelStatisticVo;
import com.example.eeuse.server.IotTaskMonitorService;
import org.dromara.easyes.core.conditions.select.LambdaEsQueryWrapper;
import org.dromara.easyes.core.kernel.EsWrappers;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.ParsedTerms;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.aggregations.metrics.ParsedSum;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author hly
 */
@Service
public class IotTaskMonitorServiceImpl implements IotTaskMonitorService {

    @Resource
    private TaskMonitorMapper taskMonitorMapper;
    @Override
    public List<ChannelStatisticVo> searchChannelStatistic(ChannelStatisticDto channelStatisticDto) {
        List<ChannelStatisticVo> channelStatisticVos = new ArrayList<>();
        String startTime = channelStatisticDto.getStartTime();
        String endTime = channelStatisticDto.getEndTime();
        // 构造 ES 查询
        LambdaEsQueryWrapper<TaskMonitor> queryWrapper = EsWrappers.lambdaQuery(TaskMonitor.class)
                .size(90)
                .between(TaskMonitor::getEndTime, startTime, endTime)
                .in(channelStatisticDto.getChannelNames()!=null && !channelStatisticDto.getChannelNames().isEmpty(),TaskMonitor::getChannelName, channelStatisticDto.getChannelNames())
                .groupBy(TaskMonitor::getType, TaskMonitor::getChannelName)
                .sum(TaskMonitor::getCardNumber)
                .sum(TaskMonitor::getSuccessNumber)
                .sum(TaskMonitor::getFailNumber)
                .sum(TaskMonitor::getExecuteTime);

        SearchResponse searchResponse = taskMonitorMapper.search(queryWrapper);
        Aggregations aggregations = searchResponse.getAggregations();

        // 获取第一层分组（按 Type）
        ParsedTerms typeAggregation = aggregations.get("typeTerms");
        for (Terms.Bucket typeBucket : typeAggregation.getBuckets()) {
            String typeKey = typeBucket.getKeyAsString();

            // 获取第二层分组（按 ChannelName）
            ParsedTerms channelAggregation = typeBucket.getAggregations().get("channelNameTerms");
            for (Terms.Bucket channelBucket : channelAggregation.getBuckets()) {
                ChannelStatisticVo channelStatisticVo = new ChannelStatisticVo();
                String channelKey = channelBucket.getKeyAsString();

                // 获取 sum 值
                Map<String, Aggregation> aggMap = channelBucket.getAggregations().asMap();
                double cardNumberSum = ((ParsedSum) aggMap.get("cardNumberSum")).getValue();
                double successNumberSum = ((ParsedSum) aggMap.get("successNumberSum")).getValue();
                double failNumberSum = ((ParsedSum) aggMap.get("failNumberSum")).getValue();
                double executeTimeSum = ((ParsedSum) aggMap.get("executeTimeSum")).getValue();

                // 查询文档数量
                Long count = taskMonitorMapper.selectCount(EsWrappers.lambdaQuery(TaskMonitor.class)
                        .between(TaskMonitor::getEndTime, startTime, endTime)
                        .eq(TaskMonitor::getType, typeKey)
                        .eq(TaskMonitor::getChannelName, channelKey));

                // 避免除零错误
                if (count == null || count == 0) {
                    count = 1L;
                }
                // 计算成功率 & 失败率，防止 cardNumberSum 为 0
                double successRate = (cardNumberSum > 0) ? (successNumberSum / cardNumberSum * 100) : 0;
                double failRate = (cardNumberSum > 0) ? (failNumberSum / cardNumberSum * 100) : 0;
                // 计算平均值，并保留两位小数
                channelStatisticVo.setType(typeKey);
                channelStatisticVo.setChannelName(channelKey);
                channelStatisticVo.setCardNumber(formatDecimal(cardNumberSum / count));
                channelStatisticVo.setSuccessNumber(formatDecimal(successNumberSum / count));
                channelStatisticVo.setFailNumber(formatDecimal(failNumberSum / count));
                //转成秒
                channelStatisticVo.setExecuteTime(formatDecimal(executeTimeSum / count / 60));
                channelStatisticVo.setSuccessRate(formatDecimal(successRate) + "%");
                channelStatisticVo.setFailRate(formatDecimal(failRate) + "%");
                channelStatisticVos.add(channelStatisticVo);
            }
        }
        return channelStatisticVos;
    }

    /**
     * 格式化数值，保留两位小数
     */
    private String formatDecimal(double value) {
        return BigDecimal.valueOf(value).setScale(2, RoundingMode.HALF_UP).toString();
    }
}
